package redis

import (
	"errors"
	"github.com/garyburd/redigo/redis"
	"time"
)

type RedisClient interface {
	//创建链接
	Connect() error
	//停止
	Stop() error
	//通用：获取ttl,返回剩余生命周期，单位秒
	TTL(key string) (int64, error)
	//通用：是否存在键名
	Existed(key string) (bool, error)
	//通用：给key设置过期，指定过期时间
	EXPIRE(key string, seconds int64) error
	//通用：给key设置过期，指定具体过期日期
	EXPIREAT(key interface{}, timestamp int64) error
	//字符串：设置键值对,永不过期,会覆盖旧值
	SET(key string, value interface{}) error
	//字符串：只在键 key 不存在的情况下， 将键 key 的值设置为 value 。
	SETNX(key string, value interface{}) error
	//字符串：将键 key 的值设置为 value ， 并将键 key 的生存时间设置为 seconds 秒钟。
	//如果键 key 已经存在， 那么 SETEX 命令将覆盖已有的值
	SETEX(key string, value interface{}, exSec int) error
	// 字符串：查询键值对
	GET(key string) (string, error)
	//字符串：将键 key 的值设为 value ， 并返回键 key 在被设置之前的旧值。
	GETSET(key string, value string) (string, error)
	//字符串：返回键 key 储存的字符串值的长度。
	STRLEN(key string) (int64, error)
	//字符串：为键 key 储存的数字值自增1
	//如果键 key 不存在， 那么它的值会先被初始化为 0 ， 然后再执行 INCR 命令。
	//如果键 key 储存的值不能被解释为数字， 那么 INCR 命令将返回一个错误
	//INCR 命令会返回键 key 在执行加一操作之后的值。
	INCR(key string) (int64, error)
	//字符串：为键 key 储存的数字值加上增量 increment 。
	//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 INCRBY 命令。
	//在加上增量 increment 之后， 键 key 当前的值。
	INCRBY(key string, increment int64) (int64, error)
	//字符串：为键 key 储存的数字值减去一。
	//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 DECR 操作。
	//DECR 命令会返回键 key 在执行减一操作之后的值。
	DECR(key string) (int64, error)
	//字符串：将键 key 储存的整数值减去减量 decrement 。
	//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 DECRBY 命令。
	//DECRBY 命令会返回键在执行减法操作之后的值。
	DECRBY(key string, increment int64) (int64, error)
	//字符串：同时为多个键设置值。会覆盖已有值
	MSET(kv map[string]interface{}) error
	//字符串：当且仅当所有给定键都不存在时， 为所有给定键设置值
	MSETNX(kv map[string]interface{}) error
	//字符串：返回给定的一个或多个字符串键的值。
	MGET(keys ...string) ([]string, error)
	//哈希：将哈希表 hash 中域 field 的值设置为 value,会覆盖已有值 。
	HSET(key, field string, value interface{}) error
	//哈希：返回哈希表中给定域的值。
	HGET(key, field string) (string, error)
	//哈希： field-value (域-值)对设置到哈希表 key 中。 此命令会覆盖哈希表中已存在的域。
	HMSET_map(key string, fieldValue map[string]interface{}) error
	//哈希： 将结构体设置到哈希表 key 中。structPointer结构体字段tag可以“redis”重命名，此命令会覆盖哈希表中已存在的域。
	HMSET_struct(key string, structPointer interface{}) error
	//哈希：返回哈希表 key 中，一个或多个给定域的值。
	//如果给定的域不存在于哈希表，那么返回一个 空 值。
	HMGET(key string, field ...string) ([]string, error)
	//哈希：获取全部解析到对象structPointer，structPointer为指针,obj的字段tag可以“redis”重命名，需自行判断obj的空值
	HGETALL_struct(key string, structPointer interface{}) error
	//哈希：指定键名是否存在某个field元素
	HEXISTS(key, field string) (bool, error)
	//哈希：删除指定键名的某个field元素
	HDEL(key string, fields ...string) error
	//哈希：返回哈希表 key 中域的数量。
	HLEN(key string) (int64, error)
	//哈希：给指定key的field字段增量increment，必须为整型
	HINCRBY(key, field string, increment int) (int64, error)
	//集合：member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略,返回新增的数量
	SADD(key string, memmbers ...string) (int64, error)
	//集合：判断member元素是否是集合key的成员
	SISMEMBER(key, memmber string) (bool, error)
	//集合：移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。
	SREM(key string, member ...string) (int64, error)
	//集合：将 member 元素从 source 集合移动到 destination 集合。
	SMOVE(source, destKey, member string) error
	//集合：返回集合 key 的基数(集合中元素的数量)。
	SCARD(key string) (int64, error)
	//集合：返回集合key所有元素
	SMEMBERS(key string) ([]string, error)
	//集合：返回一个集合的全部成员，该集合是所有给定集合的交集。
	SINTER(keys ...string) ([]string, error)
	//集合：这个命令类似于 SINTER key [key …] 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集。
	//如果 destination 集合已经存在，则将其覆盖。
	//destination 可以是 key 本身。
	SINTERSTORE(destKey string, keys ...string) error
	//集合：返回一个集合的全部成员，该集合是所有给定集合的并集。
	SUNION(keys ...string) ([]string, error)
	//集合：这个命令类似于 SUNION key [key …] 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集。
	SUNIONSTORE(destKey string, keys ...string) error
	//集合：返回一个集合的全部成员，该集合是所有给定集合之间的差集
	SDIFF(keys ...string) ([]string, error)
	//集合：这个命令的作用和 SDIFF key [key …] 类似，但它将结果保存到 destination 集合，而不是简单地返回结果集。
	SDIFFSTORE(destKey string, keys ...string) error
	//位图：对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。
	//位的设置或清除取决于 value 参数，可以是 0 也可以是 1 。返回原来指定偏移上的bit
	SETBIT(key string, offset int64, value int) (int, error)
	//位图：对 key 所储存的字符串值，获取指定偏移量上的位(bit)。
	GETBIT(key string, offset int64) (int, error)
	//位图：计算给定字符串中，被设置为 1 的比特位的数量。
	BITCOUNT(key string, start, end int64) (int64, error)
	//位图：对一个或多个保存二进制位的字符串 key 进行位元操作，并将结果保存到 destkey 上。
	//operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种：
	BITOP(operation, destKey string, keys ...string) error
	//有序集：为有序集 key 的成员 member 的 score 值加上增量 increment 。返回最终的score值
	//可以通过传递一个负数值 increment ，让 score 减去相应的值，比如 ZINCRBY key -5 member ，就是让 member 的 score 值减去 5 。
	//当 key 不存在，或 member 不是 key 的成员时， ZINCRBY key increment member 等同于 ZADD key increment member 。
	//当 key 不是有序集类型时，返回一个错误。
	ZINCRBY(key string, incerment int64, member string) (string, error)
	//有序集：返回有序集 key 中， score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
	//具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。
	ZREVRANGEBYSCORE(key string, max, min int64) ([]string, error)
	//有序集：返回有序集 key 中，成员 member 的 score 值。
	//如果 member 元素不是有序集 key 的成员，或 key 不存在，返回 nil
	ZSCORE(key string, member string) (int64, error)
}

func New(config Config) RedisClient {
	return &redisClient{
		Config: config,
	}
}

type redisClient struct {
	Config
	Pool *redis.Pool
}

type Config struct {
	Host            string
	Port            string
	DB              int
	MaxIdle         int
	MaxActive       int
	IdleTimeoutSecs int
	Password        string
}

func (this *redisClient) Connect() error {

	// 建立连接池
	this.Pool = &redis.Pool{
		// 从配置文件获取maxidle以及maxactive，取不到则用后面的默认值
		MaxIdle:     this.MaxIdle,
		MaxActive:   this.MaxActive,
		IdleTimeout: time.Duration(this.IdleTimeoutSecs) * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", this.Host+":"+this.Port)
			if err != nil {
				return nil, err
			}
			//密码校验
			if this.Password != "" {
				if _, err := c.Do("AUTH", this.Password); err != nil {
					c.Close()
					return nil, err
				}
			}
			// 选择db
			c.Do("SELECT", this.DB)

			return c, nil
		},
	}
	return nil
}

func (this *redisClient) Stop() error {
	return nil
}

//通用：获取ttl,返回剩余生命周期，单位秒
func (this *redisClient) TTL(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	seconds, err := redis.Int64(rconn.Do("TTL", key))
	return seconds, err
}

//通用：是否存在键名
func (this *redisClient) Existed(key string) (bool, error) {
	rconn := this.Pool.Get()
	booler, err := redis.Bool(rconn.Do("EXISTS", key))
	defer rconn.Close()
	return booler, err
}

//通用：给key设置过期，指定过期时间
func (this *redisClient) EXPIRE(key string, seconds int64) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	status, err := redis.Int(rconn.Do("EXPIRE", key, seconds))
	if err != nil {
		return err
	}
	if status == 1 {
		return nil
	} else {
		return errors.New("不存在或没办法设置生存时间")
	}
}

//通用：给key设置过期，指定具体过期日期
func (this *redisClient) EXPIREAT(key interface{}, timestamp int64) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	status, err := redis.Int(rconn.Do("EXPIREAT", key, timestamp))
	if err != nil {
		return err
	}
	if status == 1 {
		return nil
	} else {
		return errors.New("不存在或没办法设置生存时间")
	}
}

//字符串：设置键值对,永不过期,会覆盖旧值
func (this *redisClient) SET(key string, value interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SET", key, value)
	return err
}

//字符串：只在键 key 不存在的情况下， 将键 key 的值设置为 value 。
func (this *redisClient) SETNX(key string, value interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SETNX", key, value) //永不过期
	return err
}

//字符串：将键 key 的值设置为 value ， 并将键 key 的生存时间设置为 seconds 秒钟。
//如果键 key 已经存在， 那么 SETEX 命令将覆盖已有的值
func (this *redisClient) SETEX(key string, value interface{}, exSec int) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SETEX", key, value, exSec) //永不过期
	return err
}

// 字符串：查询键值对
func (this *redisClient) GET(key string) (string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	v, err := redis.String(rconn.Do("GET", key))
	return v, err
}

//字符串：将键 key 的值设为 value ， 并返回键 key 在被设置之前的旧值。
func (this *redisClient) GETSET(key string, value string) (string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	v, err := redis.String(rconn.Do("GETSET", key, value))
	return v, err
}

//字符串：返回键 key 储存的字符串值的长度。
func (this *redisClient) STRLEN(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	length, err := redis.Int64(rconn.Do("STRLEN", key))
	return length, err
}

//字符串：为键 key 储存的数字值自增1
//如果键 key 不存在， 那么它的值会先被初始化为 0 ， 然后再执行 INCR 命令。
//如果键 key 储存的值不能被解释为数字， 那么 INCR 命令将返回一个错误
//INCR 命令会返回键 key 在执行加一操作之后的值。
func (this *redisClient) INCR(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int64(rconn.Do("INCR", key))
	return value, err
}

//字符串：为键 key 储存的数字值加上增量 increment 。
//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 INCRBY 命令。
//在加上增量 increment 之后， 键 key 当前的值。
func (this *redisClient) INCRBY(key string, increment int64) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int64(rconn.Do("INCRBY", key, increment))
	return value, err
}

//字符串：为键 key 储存的数字值减去一。
//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 DECR 操作。
//DECR 命令会返回键 key 在执行减一操作之后的值。
func (this *redisClient) DECR(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int64(rconn.Do("DECR", key))
	return value, err
}

//字符串：将键 key 储存的整数值减去减量 decrement 。
//如果键 key 不存在， 那么键 key 的值会先被初始化为 0 ， 然后再执行 DECRBY 命令。
//DECRBY 命令会返回键在执行减法操作之后的值。
func (this *redisClient) DECRBY(key string, increment int64) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int64(rconn.Do("DECRBY", key, increment))
	return value, err
}

//字符串：同时为多个键设置值。会覆盖已有值
func (this *redisClient) MSET(kv map[string]interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("MSET", redis.Args{}.AddFlat(kv)...)
	return err
}

//字符串：当且仅当所有给定键都不存在时， 为所有给定键设置值
func (this *redisClient) MSETNX(kv map[string]interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("MSETNX", redis.Args{}.AddFlat(kv)...)
	return err
}

//字符串：返回给定的一个或多个字符串键的值。
func (this *redisClient) MGET(keys ...string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	values, err := redis.Strings(rconn.Do("MGET", redis.Args{}.AddFlat(keys)...))
	return values, err
}

//哈希：将哈希表 hash 中域 field 的值设置为 value,会覆盖已有值 。
func (this *redisClient) HSET(key, field string, value interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("HSET", key, field, value)

	return err
}

//哈希：返回哈希表中给定域的值。
func (this *redisClient) HGET(key, field string) (string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.String(rconn.Do("HGET", key, field))
	return value, err
}

//哈希： field-value (域-值)对设置到哈希表 key 中。 此命令会覆盖哈希表中已存在的域。
func (this *redisClient) HMSET_map(key string, fieldValue map[string]interface{}) error {
	rconn := this.Pool.Get()
	_, err := rconn.Do("HMSET", redis.Args{}.Add(key).AddFlat(fieldValue)...)
	defer rconn.Close()
	return err
}

//哈希： 将结构体设置到哈希表 key 中。structPointer结构体字段tag可以“redis”重命名，此命令会覆盖哈希表中已存在的域。
func (this *redisClient) HMSET_struct(key string, structPointer interface{}) error {
	rconn := this.Pool.Get()
	_, err := rconn.Do("HMSET", redis.Args{}.Add(key).AddFlat(structPointer)...)
	defer rconn.Close()
	return err
}

//哈希：返回哈希表 key 中，一个或多个给定域的值。
//如果给定的域不存在于哈希表，那么返回一个 空 值。
func (this *redisClient) HMGET(key string, field ...string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	v, err := redis.Strings(rconn.Do("HMGET", redis.Args{}.Add(key).AddFlat(field)...))
	return v, err
}

//哈希：获取全部解析到对象structPointer，structPointer为指针,obj的字段tag可以“redis”重命名，需自行判断obj的空值
func (this *redisClient) HGETALL_struct(key string, structPointer interface{}) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	val, err := redis.Values(rconn.Do("HGETALL", key))
	if err != nil {
		return err
	}
	if len(val) == 0 {
		return errors.New("不存在的key")
	}
	err = redis.ScanStruct(val, structPointer)
	if err != nil {
		return err
	}
	return nil
}

//哈希：指定键名是否存在某个field元素
func (this *redisClient) HEXISTS(key, field string) (bool, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	isExist, err := redis.Bool(rconn.Do("HEXISTS", key, field))
	return isExist, err
}

//哈希：删除指定键名的某个field元素
func (this *redisClient) HDEL(key string, fields ...string) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("HDEL", redis.Args{}.Add(key).AddFlat(fields)...)
	return err
}

//哈希：返回哈希表 key 中域的数量。
func (this *redisClient) HLEN(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	num, err := redis.Int64(rconn.Do("HLEN", key))
	return num, err
}

//哈希：给指定key的field字段增量increment，必须为整型
func (this *redisClient) HINCRBY(key, field string, increment int) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	num, err := redis.Int64(rconn.Do("HINCRBY", key, field, increment))
	return num, err
}

//集合：member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略,返回新增的数量
func (this *redisClient) SADD(key string, memmbers ...string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	numAdded, err := redis.Int64(rconn.Do("SADD", redis.Args{}.Add(key).AddFlat(memmbers)...))
	return numAdded, err
}

//集合：判断member元素是否是集合key的成员
func (this *redisClient) SISMEMBER(key, memmber string) (bool, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	flag, err := redis.Int(rconn.Do("SISMEMBER", key, memmber))
	if err != nil {
		return false, err
	} else {
		if flag == 0 {
			return false, nil
		} else {
			return true, nil
		}
	}
}

//集合：移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。
func (this *redisClient) SREM(key string, member ...string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	num, err := redis.Int64(rconn.Do("SREM", redis.Args{}.Add(key).AddFlat(member)...))
	return num, err
}

//集合：将 member 元素从 source 集合移动到 destination 集合。
func (this *redisClient) SMOVE(source, destKey, member string) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SMOVE", source, destKey, member)
	return err
}

//集合：返回集合 key 的基数(集合中元素的数量)。
func (this *redisClient) SCARD(key string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	num, err := redis.Int64(rconn.Do("SCARD", key))
	return num, err
}

//集合：返回集合key所有元素
func (this *redisClient) SMEMBERS(key string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	strArry, err := redis.Strings(rconn.Do("SMEMBERS", key))
	return strArry, err
}

//集合：返回一个集合的全部成员，该集合是所有给定集合的交集。
func (this *redisClient) SINTER(keys ...string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	strArry, err := redis.Strings(rconn.Do("SINTER", keys))
	return strArry, err
}

//集合：这个命令类似于 SINTER key [key …] 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集。
//如果 destination 集合已经存在，则将其覆盖。
//destination 可以是 key 本身。
func (this *redisClient) SINTERSTORE(destKey string, keys ...string) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SINTERSTORE", redis.Args{}.Add(destKey).AddFlat(keys)...)
	return err
}

//集合：返回一个集合的全部成员，该集合是所有给定集合的并集。
func (this *redisClient) SUNION(keys ...string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	strArry, err := redis.Strings(rconn.Do("SUNION", keys))
	return strArry, err
}

//集合：这个命令类似于 SUNION key [key …] 命令，但它将结果保存到 destination 集合，而不是简单地返回结果集。
func (this *redisClient) SUNIONSTORE(destKey string, keys ...string) error {

	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SUNIONSTORE", redis.Args{}.Add(destKey).AddFlat(keys)...)
	return err
}

//集合：返回一个集合的全部成员，该集合是所有给定集合之间的差集
func (this *redisClient) SDIFF(keys ...string) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	strArry, err := redis.Strings(rconn.Do("SDIFF", keys))
	return strArry, err
}

//集合：这个命令的作用和 SDIFF key [key …] 类似，但它将结果保存到 destination 集合，而不是简单地返回结果集。
func (this *redisClient) SDIFFSTORE(destKey string, keys ...string) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("SDIFFSTORE", redis.Args{}.Add(destKey).AddFlat(keys)...)
	return err
}

//位图：对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。
//位的设置或清除取决于 value 参数，可以是 0 也可以是 1 。返回原来指定偏移上的bit
func (this *redisClient) SETBIT(key string, offset int64, value int) (int, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	oldBit, err := redis.Int(rconn.Do("SETBIT", key, offset, value))
	return oldBit, err
}

//位图：对 key 所储存的字符串值，获取指定偏移量上的位(bit)。
func (this *redisClient) GETBIT(key string, offset int64) (int, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int(rconn.Do("GETBIT", key, offset))
	return value, err
}

//位图：计算给定字符串中，被设置为 1 的比特位的数量。
func (this *redisClient) BITCOUNT(key string, start, end int64) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	value, err := redis.Int64(rconn.Do("BITCOUNT", key, start, end))
	return value, err
}

//位图：对一个或多个保存二进制位的字符串 key 进行位元操作，并将结果保存到 destkey 上。
//operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种：
func (this *redisClient) BITOP(operation, destKey string, keys ...string) error {
	rconn := this.Pool.Get()
	defer rconn.Close()
	_, err := rconn.Do("BITOP", redis.Args{}.Add(operation).Add(destKey).AddFlat(keys)...)
	return err
}

//有序集：为有序集 key 的成员 member 的 score 值加上增量 increment 。返回最终的score值
//可以通过传递一个负数值 increment ，让 score 减去相应的值，比如 ZINCRBY key -5 member ，就是让 member 的 score 值减去 5 。
//当 key 不存在，或 member 不是 key 的成员时， ZINCRBY key increment member 等同于 ZADD key increment member 。
//当 key 不是有序集类型时，返回一个错误。
func (this *redisClient) ZINCRBY(key string, incerment int64, member string) (string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	scoreStr, err := redis.String(rconn.Do("ZINCRBY", key, incerment, member))
	return scoreStr, err
}

//有序集：返回有序集 key 中， score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
//具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。
func (this *redisClient) ZREVRANGEBYSCORE(key string, max, min int64) ([]string, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	memberArry, err := redis.Strings(rconn.Do("ZREVRANGEBYSCORE", key, max, min))
	return memberArry, err
}

//有序集：返回有序集 key 中，成员 member 的 score 值。
//如果 member 元素不是有序集 key 的成员，或 key 不存在，返回 nil
func (this *redisClient) ZSCORE(key string, member string) (int64, error) {
	rconn := this.Pool.Get()
	defer rconn.Close()
	score, err := redis.Int64(rconn.Do("ZSCORE", key, member))
	return score, err
}
